// Copyright (C) 1953-2022 NUDT
// Verilog module name - fit_lookup
// Version: V4.0.0.20231225
// Created:
//         by - fenglin 
////////////////////////////////////////////////////////////////////////////
// Description:
//         lookup fit forward table.
///////////////////////////////////////////////////////////////////////////


module fit_lookup
(
        i_clk               ,
        i_rst_n             ,
        
        iv_fifo_rdata       ,
        i_fifo_empty        ,
		o_fifo_rd           ,
		
		i_fifo_full			,
               
        o_fitram_rd         ,
        ov_fitram_raddr     ,
        iv_fitram_rdata     ,
                              
        ov_pkt_abstract     ,
        ov_pkt_abstract_wr  ,
		
        iv_mirror_mode        
);
// I/O
// clk & rst  
input               i_clk;
input               i_rst_n;
//
input       [127:0] iv_fifo_rdata;
input               i_fifo_empty;
output reg          o_fifo_rd;

input               i_fifo_full;

output reg          o_fitram_rd;
output reg  [3:0]   ov_fitram_raddr;
input       [14:0]  iv_fitram_rdata;
//output 
output reg  [127:0] ov_pkt_abstract;
output reg          ov_pkt_abstract_wr;

input       [1:0]   iv_mirror_mode;

reg         [127:0] rv_pkt_abstract;

//***************************************************
//          lookup fit table
//***************************************************

reg         [3:0]   fit_state;
localparam  IDLE_S                = 4'd0,
            WAIT_FIRST_S          = 4'd1,
            WAIT_SECOND_S         = 4'd2,
            LOOKUP_FIT_TABLE_S    = 4'd3,
            OUTPUT_ALL_MD_S       = 4'd4;
always @(posedge i_clk or negedge i_rst_n)begin
    if(!i_rst_n)begin      
        ov_fitram_raddr           <= 4'd0;
        o_fitram_rd               <= 1'b0;                                   
		o_fifo_rd                 <= 1'b0;                            
        ov_pkt_abstract           <= 128'b0;
		ov_pkt_abstract_wr        <= 1'b0;    
		rv_pkt_abstract           <= 128'b0;
        fit_state                 <= IDLE_S;
    end
    else begin
        case(fit_state)
            IDLE_S:begin
				if(iv_mirror_mode==2'b11)begin
					fit_state      <= IDLE_S;
					ov_pkt_abstract           <= 128'b0;
					ov_pkt_abstract_wr        <= 1'b0;					
					if(!i_fifo_empty)begin
						o_fifo_rd             <= 1'b1;
						rv_pkt_abstract       <= iv_fifo_rdata;
						fit_state             <= OUTPUT_ALL_MD_S;
					end
					else begin 
						o_fifo_rd                 <= 1'b0;
						fit_state                 <= IDLE_S;
					end	
				end
				else begin				
					if(!i_fifo_empty)begin
						ov_fitram_raddr           <= 6'd0;
						o_fitram_rd               <= 1'b1;                          
						o_fifo_rd                 <= 1'b1;                                                     
						rv_pkt_abstract           <= iv_fifo_rdata;
						ov_pkt_abstract           <= 128'b0;
						ov_pkt_abstract_wr        <= 1'b0;
					    fit_state                 <= WAIT_FIRST_S;
					end
					else begin                 
						ov_fitram_raddr           <= 6'd0;
						o_fitram_rd               <= 1'b0;                                                       
						o_fifo_rd                 <= 1'b0;                                             
						ov_pkt_abstract           <= 128'b0;
						ov_pkt_abstract_wr        <= 1'b0;
						fit_state                 <= IDLE_S;                 
					end
				end
            end
			OUTPUT_ALL_MD_S:begin//get data of reading fifo after 1 cycles.               
				if(!i_fifo_full)begin
					ov_pkt_abstract           <= rv_pkt_abstract;
					ov_pkt_abstract_wr        <= 1'b1; 					
				end
				else begin
					ov_pkt_abstract           <= 128'b0;
					ov_pkt_abstract_wr        <= 1'b0; 							
				end              
                o_fifo_rd                     <= 1'b0;
				fit_state                     <= IDLE_S;
			end
            WAIT_FIRST_S:begin//get data of reading ram after 2 cycles.               
                o_fitram_rd                   <= 1'b1;
                ov_fitram_raddr               <= ov_fitram_raddr + 1'b1;  			
                o_fifo_rd                     <= 1'b0;                
                fit_state                     <= WAIT_SECOND_S;
			end
			WAIT_SECOND_S:begin               
                o_fitram_rd                   <= 1'b1;
                ov_fitram_raddr               <= ov_fitram_raddr + 1'b1;              
                o_fifo_rd                     <= 1'b0;                
                fit_state                     <= LOOKUP_FIT_TABLE_S;
			end
			LOOKUP_FIT_TABLE_S:begin
				if(iv_fitram_rdata[14] == 1'b1)begin//table entry is valid
                    if(iv_fitram_rdata[13:0] == rv_pkt_abstract[45:32])begin//fit compare.
                        ov_fitram_raddr        <= 4'b0; 
						o_fitram_rd            <= 1'b0;					
						if(!i_fifo_full)begin
							ov_pkt_abstract           <= rv_pkt_abstract;
							ov_pkt_abstract_wr        <= 1'b1; 					
						end
						else begin
							ov_pkt_abstract           <= 128'b0;
							ov_pkt_abstract_wr        <= 1'b0; 							
						end  
					    fit_state              <= IDLE_S; 
                    end
                    else begin
						if(ov_fitram_raddr == 4'h01)begin
						    o_fitram_rd        <= 1'b0;
                            ov_fitram_raddr    <= 4'b0;
							ov_pkt_abstract    <= 128'b0;
							ov_pkt_abstract_wr <= 1'b0; 
							fit_state          <= IDLE_S;
						end
						else begin
							ov_fitram_raddr    <= ov_fitram_raddr + 1'b1; 
							o_fitram_rd        <= 1'b1;
							ov_pkt_abstract    <= 128'b0;
							ov_pkt_abstract_wr <= 1'b0; 
							fit_state          <= LOOKUP_FIT_TABLE_S;
						end
                    end
                end
                else begin
                    o_fitram_rd        <= 1'b0;
                    ov_fitram_raddr    <= 4'b0;
                    o_fifo_rd          <= 1'b0;  
					ov_pkt_abstract    <= 128'b0;
					ov_pkt_abstract_wr <= 1'b0; 					
                    fit_state       <= IDLE_S;                        
                end			
			end
            default:begin             
                ov_fitram_raddr     <= 4'd0;
                o_fitram_rd         <= 1'b0;                                                 
                o_fifo_rd           <= 1'b0;                                          
                ov_pkt_abstract     <= 128'b0;
                ov_pkt_abstract_wr  <= 1'b0;
                fit_state           <= IDLE_S;             
            end
        endcase
    end
end
endmodule           
